package com.heisen.database.controller;

import com.heisen.base.entity.Api;
import com.heisen.base.exception.RRException;
import com.heisen.base.utils.GsonUtils;
import com.heisen.database.entity.IBaseEntity;
import com.heisen.database.entity.PageQuery;
import com.heisen.database.service.ISuperService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author sen
 * @param <T> 实体对象
 * @param <E> update 和 save 对象的dto
 * @param <Q> 分页对象
 * @param <S>  service 对象
 * @description  抽象Controller  实现 增删改查 基本的接口   doPage分页接口有点特殊  需要在mapper。xml 文件实现  doPage 的sql 完成分页
 * @date 2024/1/8 15:49
 */
@Slf4j
public abstract class AbstractController <T , E extends IBaseEntity , Q extends PageQuery ,S extends ISuperService> {

    // 这个可以使用 自定义的servicce 继承IService  可以见ISuperService
  //  protected abstract ISuperService<T,Q> getService();

    /**
     * 通过注入的方式 获取service对象
     */
    @Autowired
    public S service;

   // protected abstract Class<T> getEntityClass();

    /**
     * 获取到T的 class 类型
     * @return
     */
    public Class<T> getTClass() {

        Type type = getClass().getGenericSuperclass();
        if(!(type instanceof ParameterizedType)) {
            throw new IllegalStateException("Type must be a parameterized type");
        }
        ParameterizedType parameterizedType = (ParameterizedType)type;
        // 获取泛型的具体类型  这里是单泛型
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        if(null == actualTypeArguments || actualTypeArguments.length<1) {
            throw new IllegalStateException("Number of type arguments must be 1");
        }
        return (Class<T>) actualTypeArguments[0];
    }

    /**
     *  转换对象
     * @param form
     * @return
     */
    protected T formConvert(E form ) {
        return GsonUtils.toBean(GsonUtils.toJson(form), this.getTClass());
    }


    /**
     *  新增一条记录
     *
     * @param addDto 对象
     * @return 新增结果
     */
    @PostMapping(name="添加{}")
    public Api save(@RequestBody @Valid E addDto) {
        T entity = formConvert(addDto);
      //  return Api.ok(getService().save(entity));

        return   Api.of(service.save(entity)).build();
    }

    /**
     * 分页查询  doPage 分页
     * @deprecated 分页接口有点特殊  需要在mapper。xml 文件实现  doPage 的sql 完成分页
     * @param page 查询条件
     * @return 分页列表
     */
    @PostMapping(path = "/doPage", name="分页查询{}")
   // @Deprecated
    public Api doPage(@RequestBody Q page) {
        return Api.ok(service.doPage(page));

    }




    
    /**
     * 根据主键获取实体对象
     *
     * @param id 主键
     * @return 告警通知
     */
    @GetMapping(path = "/{id}",name="获取{}")
    public Api get(@PathVariable("id") Long id) {
        if(id == null) throw  new RRException("id  为空");
        return Api.ok(service.getById(id));
    }

    /**
     * 修改对象
     * @param updateDto 修改对象
     * @return 修改结果
     */
    @PutMapping(path = "/{id}", name="修改{}")
    public Api update(@PathVariable Long id, @Valid @RequestBody E updateDto) {
        if(id == null ) throw  new RRException("id 为空");
        if(updateDto.getId()== null) throw  new RRException("对象id为空");
        if(!id.equals(updateDto.getId()) ) throw  new RRException("id异常");
        if(service.getById(id) == null) throw  new RRException("没有找到该对象");
        T entity = formConvert(updateDto);
        return   Api.of(service.updateById(entity))
                .build();
    }

    /**
     * 根据主键删除数据
     * @param id 主键
     * @return 删除结果
     */
    @DeleteMapping(path = "/{id}", name="删除{}")
    public Api delete(@PathVariable Long id) {
        if(id == null) throw  new RRException("id  为空");
        if(service.getById(id) == null) throw  new RRException("没有找到该对象 or 该对象以删除");
        return   Api.of(service.removeById(id))
                .build();
    }

}
